const fs = require('fs')
const path = require('path')
const Koa = require('koa')
const body = require('koa-body')
const LRU = require('lru-cache')
const validate = require('koa-validate')
const CronController = require('./controllers/cron')
// const cors = require('@koa/cors')
// const jwt = require('koa-jwt')
const instance = new CronController()
const koaStatic = require('koa-static')
const { createBundleRenderer } = require('vue-server-renderer')

const isProd = process.env.NODE_ENV === 'production'

const createRenderer = (bundle, options) => {
  return createBundleRenderer(bundle, {
    ...options,
    cache: LRU({
      max: 10000
    }),
    basedir: path.resolve(__dirname, './dist')
  })
}

const getHtml = (renderer, ctx, readyPromise) => {
  const context = {
    url: ctx.url
  }
  return new Promise((resolve, reject) => {
    const cb = (err, html) => {
      if (err) return reject(err)
      resolve(html)
    }
    if (isProd) return renderer.renderToString(context, cb)
    readyPromise.then(() => renderer.renderToString(context, cb))
  })
}

const render = app => {
  const template = fs.readFileSync(path.resolve(__dirname, './views/index.html'), 'utf-8')
  let renderer
  let readyPromise
  if (isProd) {
    const bundle = require('./dist/vue-ssr-server-bundle.json')
    const clientManifest = require('./dist/vue-ssr-client-manifest.json')
    renderer = createRenderer(bundle, {
      template,
      clientManifest
    })
  } else {
    readyPromise = require('./build/setup-dev-server')(app, path.resolve(__dirname, './views/index.html'), (bundle, options) => {
      renderer = createRenderer(bundle, options)
    })
  }

  return async function (ctx) {
    try {
      const html = await getHtml(renderer, ctx, readyPromise)
      ctx.type = 'html'
      ctx.body = html
    } catch (e) {
      if (e.code === 401) {
        ctx.status = 302
        ctx.redirect = '/login'
      } else {
        ctx.throw(e)
      }
    }
  }
}

const app = module.exports = new Koa()
const routerConfig = require('./router-config')

validate(app)

app.use(koaStatic(path.resolve(__dirname, './dist/')))
// app.use(cors())
app.use(body())

app.use(routerConfig.api.routes())
app.use(routerConfig.api.allowedMethods())

app.use(render(app))

app.listen(3000)

instance.start()
